/* typehints:start */
import { Application } from "../../application";
/* typehints:end */

import { createLogger } from "../utils/logging"
import { globalConfig } from "../../config/global";
import { clamp } from "../utils/utils";

const logger = createLogger('sound')

export const SOUNDS = {
  uiClick: 'ui/click',
  dialogOk: 'ui/dialog_ok',
  dialogError: 'ui/dialog_error',

  basicAtk: 'game/battle/basic_atk',
}

export const MUSIC = {
  default: 'default'
}

/**
 * 音效接口定义
 */
export class SoundInstanceInterface{
  constructor(key, url){
    this.key = key;
    this.url = url;
  }

  /**
   * 加载
   * @returns {Promise<void>}
   */
  load(){
    abstract;
    return Promise.resolve();
  }

  /**
   * 播放
   * @param {*} volume 
   */
  play(volume){
    abstract;
  }

  /**
   * 清除
   */
  deinitialize(){}
}

/**
 * 背景音效接口定义
 */
export class MusicInstanceInterface {
  constructor(key, url) {
    this.key = key;
    this.url = url;
  }

  stop() {
    abstract;
  }

  play(volume) {
    abstract;
  }

  setVolume(volume) {
    abstract;
  }

  /** @returns {Promise<void>} */
  load() {
    abstract;
    return Promise.resolve();
  }

  /** @returns {boolean} */
  isPlaying() {
    abstract;
    return false;
  }

  deinitialize() {}
}

export class SoundInterface{
  constructor(app, soundClass, musicClass){
    /** @type {Application} */
    this.app = app;

    this.soundClass = soundClass;
    this.musicClass = musicClass;

    /** @type {Object<string, SoundInstanceInterface>} */
    this.sounds = {};
    /** @type {Object<string, MusicInstanceInterface>} */
    this.music = {};

    /** @type {MusicInstanceInterface} */
    this.currentMusic = null;

    this.musicVolume = 1.0;
    this.soundVolume = 1.0;
    this.soundSwitch = false;

    this.pageIsVisible = true;
  }

  initialize(){
    for(const soundKey in SOUNDS){
      const soundPath = SOUNDS[soundKey];
      const sound = new this.soundClass(soundKey, soundPath);
      this.sounds[soundPath] = sound;
    }

    for(const musicKey in MUSIC){
      const musicPath = MUSIC[musicKey];
      const music = new this.musicClass(musicKey, musicPath);
      this.music[musicPath] = music;
    }

    this.musicVolume = this.app.setting.getSetting('musicVolume')
    this.soundVolume = this.app.setting.getSetting('soundVolume')
    this.soundSwitch = this.app.setting.getSetting('soundSwitch');

    if(G_IS_DEV && globalConfig.debug.disableMusic){
      // this.musicVolume = 0.0;
      this.soundSwitch = true;
    }

    return Promise.resolve();
  }

  /**
   * 预加载音乐
   * @param {*} key 
   */
  loadSound(key){
    if(this.sounds[key]){
      return this.sounds[key].load();
    } else if(this.music[key]){
      return this.music[key].load();
    } else {
      logger.error('key为', key,'的Sound/Music不存在');
      return Promise.resolve();
    }
  }

  deinitialize(){
    const promises = [];
    for(const key in this.sounds){
      promises.push(this.sounds[key].deinitialize());
    }
    for(const key in this.music){
      promises.push(this.music[key].deinitialize());
    }
    return Promise.all(...promises);
  }

  setMusicVolume(volume){
    this.musicVolume = clamp(volume, 0, 1);
    if(this.currentMusic){
      this.currentMusic.setVolume(this.musicVolume);
    }
  }

  setSoundVolume(volume){
    this.soundVolume = clamp(volume, 0, 1);
  }

  /**
   * 切换静音
   */
  setSoundSwitch(value){
    this.soundSwitch = value;
    if(this.currentMusic){
      if(!value){
        this.currentMusic.play(this.musicVolume);
      } else {
        this.currentMusic.stop();
      }
    }
  }

  /**
   * 用户离开页面，页面不可见
   * @param {Boolean} pageIsVisible 
   */
  onPageRenderableStateChanged(pageIsVisible){
    this.pageIsVisible = pageIsVisible;
    if(this.currentMusic){
      if(pageIsVisible){
        if(!this.currentMusic.isPlaying() && !this.soundSwitch){
          this.currentMusic.play(this.musicVolume);
        }
      } else {
        this.currentMusic.stop();
      }
    }
  }

  /**
   * 播放音效
   * @param {*} key 
   * @returns 
   */
  playUiSound(key){
    if(!this.sounds[key]){
      logger.warn('Sound', key, '不存在');
      return;
    }

    if(this.soundSwitch) return;

    this.sounds[key].play(this.soundVolume)
  }

  /**
   * 播放背景音乐
   * @param {*} key 
   * @returns 
   */
  playThemeMusic(key){
    const music = this.music[key]
    if(key === null) return;
    if(!music){
      logger.warn('Music', key, '不存在')
      return;
    }

    if(this.currentMusic !== music){
      if(this.currentMusic){
        logger.log('Stopping', this.currentMusic.key)
        this.currentMusic.stop();
      }
      this.currentMusic = music;

      if(this.pageIsVisible && !this.soundSwitch){
        music.play(this.musicVolume);
      }
    }
  }
}